home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / packer / tar / src / amiga.c next >
C/C++ Source or Header  |  1995-03-09  |  6KB  |  293 lines

  1. #include <exec/types.h>
  2. #include <libraries/dos.h>
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <errno.h>
  6. #define NARGS        /* get it to shut up about my mkdir */
  7. #include <stdio.h>
  8. #include "tar.h"
  9.  
  10. umask(int mask)
  11. {
  12.     return (0);
  13. }
  14.  
  15. stat(char *filename, struct stat * statbuf)
  16. {
  17.     struct FileLock *alock, *parent;
  18.     struct FileInfoBlock *fib;
  19.     int modes;
  20.     extern long timezone;
  21.  
  22.     if ((!statbuf) || (!filename))
  23.     {
  24.     errno = EFAULT;
  25.     return (-1);
  26.     }
  27.     if (alock = Lock(filename, ACCESS_READ))
  28.     {
  29.     if ((fib = (struct FileInfoBlock *) malloc(sizeof(*fib))) == NULL)
  30.     {
  31.         UnLock(alock);
  32.         errno = ENOMEM;
  33.         return (-1);    /* malloc failed */
  34.     }
  35.     Examine(alock, fib);
  36.     if (!(parent = ParentDir(alock)))
  37.     {
  38.         statbuf->st_mode = 0700;
  39.         statbuf->st_prot = ~0xf;
  40.     }
  41.     else
  42.     {
  43.         UnLock(parent);
  44.         modes = (~fib->fib_Protection >> 1) & 0x7;
  45.         statbuf->st_mode = (modes << 6);
  46.         statbuf->st_prot = fib->fib_Protection;
  47.     }
  48.     if (fib->fib_EntryType > 0)
  49.         statbuf->st_mode |= S_IFDIR;
  50.     else
  51.         statbuf->st_mode |= S_IFREG;
  52.     statbuf->st_dev = 0;
  53.     statbuf->st_ino = 0;
  54.     statbuf->st_size = fib->fib_Size;
  55.     statbuf->st_rdev = fib->fib_DiskKey;
  56.     statbuf->st_gid = 0;
  57.     statbuf->st_uid = 0;
  58.  
  59.     /*
  60.      * getft() doesn't compensate for time zones.
  61.      */
  62.     statbuf->st_mtime = getft(filename) + timezone;
  63.     statbuf->st_nlink = 1;
  64.  
  65.     /*
  66.      * These next fields really only exist for Amiga tar's benefit
  67.      */
  68.     strcpy(statbuf->st_comment, fib->fib_Comment);
  69.     memcpy((char *) &(statbuf->st_date), (char *) &(fib->fib_Date),
  70.            sizeof(statbuf->st_date));
  71.     free(fib);
  72.     UnLock(alock);
  73.     return (0);
  74.     } else
  75.     {
  76.     errno = ENOENT;
  77.     return (-1);        /* couldn't access file */
  78.     }
  79. }
  80.  
  81.  
  82. /*
  83.  * Convert Amiga style path to UNIX style. Does the following conversions:
  84.  * ull string => ./ leading /   => ../
  85.  */
  86. char *
  87. cvtAmi2UNIX(char *src, char *dst)
  88. {
  89.     char *dstp,
  90.     *srcp;
  91.  
  92.     if (!*src)
  93.     {
  94.     strcpy(dst, "./");
  95.     return (dst);
  96.     }
  97.     dstp = dst;
  98.     srcp = src;
  99. /*
  100.  * Each leading / converts to ../
  101.  */
  102.     while (*srcp == '/')
  103.     {
  104.     *dstp++ = '.';
  105.     *dstp++ = '.';
  106.     *dstp++ = '/';
  107.     srcp++;
  108.     }
  109.     while (*dstp++ = *srcp++)    /* copy rest of chars */
  110.     ;
  111.     return (dst);
  112. }
  113.  
  114. /*
  115.  * Convert UNIX style path to Amiga style. Does the following conversions:
  116.  * /  => null string ../ => /
  117.  */
  118. cvtUNIX2Ami(char *dst)
  119. {
  120.     char *dstp,
  121.     *srcp,
  122.      src[NAMSIZ + 2];
  123.  
  124.     strcpy(src, dst);
  125.     dstp = dst;
  126.     srcp = src;
  127.  
  128.     while (*srcp == '.')
  129.     {
  130.     if (*(srcp + 1) == '/')
  131.         srcp += 2;        /* ./ gets skipped */
  132.     else if ((*(srcp + 1) == '.') && (*(srcp + 2) == '/'))
  133.     {
  134.         srcp += 3;        /* ../ turns into / */
  135.         *dstp++ = '/';
  136.     } else
  137.         break;
  138.     }
  139.     while (*dstp++ = *srcp++)    /* copy rest of chars */
  140.     ;
  141.     return (dst);
  142. }
  143.  
  144.  
  145. /*
  146.  * Wrapper for SetComment.  "Smart" because it knows how to handle "", and
  147.  * handle case if current directory is root.  But not so smart it can handle
  148.  * case when we're sitting in a directory it wants to SetComment on other than
  149.  * "".
  150.  */
  151. SmartSetComment(char *filename, char *comment)
  152. {
  153.     extern int SetComment();
  154.  
  155.     if (!*comment)
  156.     return(0);
  157.     else
  158.     return(SmartDoSomething(filename, (int) comment, SetComment,
  159.                 "SetComment"));
  160. }
  161.  
  162.  
  163. /*
  164.  * Wrapper for SetProtection.  "Smart" because it knows how to handle "", and
  165.  * handle case if current directory is root.  But not so smart it can handle
  166.  * case when we're sitting in a directory it wants to SetProtection on other
  167.  * than "".
  168.  */
  169. SmartSetProtection(char *filename, int protection)
  170. {
  171.     extern int SetProtection();
  172.  
  173.     return(SmartDoSomething(filename, protection, SetProtection,
  174.                 "SetProtection"));
  175. }
  176.  
  177.  
  178. SmartDoSomething(char *filename, int arg, int (*doSomething)(), char *funcstr)
  179. {
  180.     struct FileLock *lock = 0, *parentLock;
  181.     struct FileInfoBlock *fib = 0;
  182.     int retval;
  183.  
  184.     if (*filename)
  185.     {
  186.     if (!(*doSomething)(filename, arg))
  187.      {
  188.         errno = ENOENT;
  189.         return(-1);
  190.     }
  191.     else
  192.         return(0);
  193.     }
  194.     if (filename[strlen(filename) - 1] == ':')
  195.     {
  196.     errno =  EACCES;        /* root dir */
  197.     return(-1);
  198.     }
  199.  
  200.    /*
  201.      * "" (current directory) case
  202.      *
  203.      * There are a couple things to worry about here.  First of all, you have
  204.      * to find the parent directory, and the name of the current directory.
  205.      * But if there is no parent, you can't set the comment.  Once you get
  206.      * past this, you have to change directories and unlock the old current
  207.      * directory because you can't set the protection on a busy directory.
  208.      */
  209.     if (!(lock = Lock("", ACCESS_READ)))
  210.     {
  211.     errno = ENOENT;
  212.     return (-1);
  213.     }
  214.     if (!(parentLock = ParentDir(lock)))
  215.     {
  216.     UnLock(lock);
  217.     errno = EACCES;        /* root dir */
  218.     return (-1);
  219.     }
  220.     if (!(fib = (struct FileInfoBlock *) malloc(sizeof(*fib))))
  221.     {
  222.     UnLock(lock);
  223.     errno = ENOMEM;
  224.     return (-1);
  225.     }
  226.     Examine(lock, fib);
  227.     UnLock(lock);        /* free Lock obtained by Lock("",) */
  228.  
  229.     /*
  230.      * At this point we have a FileInfoBlock with the name of this directory,
  231.      * and a lock on our parent directory.  CD to the parent directory, unlock
  232.      * the old directory, and set the comment.
  233.      */
  234.     lock = CurrentDir(parentLock);
  235.     UnLock(lock);        /* free Lock held by shell??? */
  236.     if (!(*doSomething)(fib->fib_FileName, arg))
  237.     {
  238.     errno = ENOENT;
  239.     retval = -1;
  240.     }
  241.     else
  242.     retval = 0;
  243.  
  244.     /*
  245.      * Whew, now cleanup.  Remember, we are now in the parent directory.
  246.      */
  247.     lock = Lock(fib->fib_FileName);
  248.     parentLock = CurrentDir(lock);
  249.     UnLock(parentLock);
  250.     free(fib);
  251.     return (retval);
  252. }
  253.  
  254. /*
  255.  * Lattice C perror() puts out a leading \n - this is the wrong behavior
  256.  */
  257. perror(char *s)
  258. {
  259.     if ((errno >= 0) && (errno <= sys_nerr))
  260.     {
  261.     fputs(s, stderr);
  262.     fputs(": ", stderr);
  263.     fputs(sys_errlist[errno], stderr);
  264.     putc('\n', stderr);
  265.     fflush(stderr);        /* why do I have to do this???  It shouldn't
  266.                    be buffered. */
  267.     }
  268.     return(errno);
  269. }
  270.  
  271. /*
  272.  * It's probably cleaner to write my own mkdir() which takes two arguments,
  273.  * rather than paste in the code to set the mode everywhere mkdir() is
  274.  * called
  275.  */
  276. mkdir(char *dirname, int mode)
  277. {
  278.     struct FileLock *lock;
  279.  
  280.     if (lock = CreateDir(dirname))
  281.     {
  282.     UnLock(lock);
  283.     return(SmartSetProtection(dirname, (~(((mode & 0700) >> 5) | 1)) & 0xf));
  284.     }
  285.     else
  286.     {
  287.     if (IoErr() == ERROR_DIRECTORY_NOT_EMPTY)
  288.         return(0);
  289.      errno = EACCES;        /* FIXME */
  290.     return(-1);
  291.     }
  292. }
  293.